//获取图片主色
function getImageColor(img, imageData) {
  console.log(img);
  let r = 0,
    g = 0,
    b = 0
  // 取所有像素的平均值
  for (let row = 0; row < img.height; row++) {
    for (let col = 0; col < img.width; col++) {
      r += imageData[(img.width * row + col) * 4]
      g += imageData[(img.width * row + col) * 4 + 1]
      b += imageData[(img.width * row + col) * 4 + 2]
    }
  }
  // 求取平均值
  r /= img.width * img.height
  g /= img.width * img.height
  b /= img.width * img.height
  // 将最终的值取整
  r = Math.round(r)
  g = Math.round(g)
  b = Math.round(b)
  //rgb转16进制 位运算
  const color = ((r << 16) | (g << 8) | b).toString(16)
  var mColor = "#" + color
  return mColor
}

//反色（负片）效果
function reverseColor(imageDatas) {
  var imageData = imageDatas
  var imageData_length = imageData.data.length / 4;
  // 解析之后进行算法运算
  for (var i = 0; i < imageData_length; i++) {
    imageData.data[i * 4] = 255 - imageData.data[i * 4];
    imageData.data[i * 4 + 1] = 255 - imageData.data[i * 4 + 1];
    imageData.data[i * 4 + 2] = 255 - imageData.data[i * 4 + 2];
  }
  return imageData
}

//去色效果
function removeColor(imageDatas) {
  var imageData = imageDatas
  var imageData_length = imageData.data.length / 4;
  // 解析之后进行算法运算
  for (var i = 0; i < imageData_length; i++) {
    var red = imageData.data[i * 4];
    var green = imageData.data[i * 4 + 1];
    var blue = imageData.data[i * 4 + 2];
    var gray = 0.3 * red + 0.59 * green + 0.11 * blue;
    imageData.data[i * 4] = gray;
    imageData.data[i * 4 + 1] = gray;
    imageData.data[i * 4 + 2] = gray;
  }
  return imageData
}
//单色效果
function singleColor(imageData) {
  var imageData_length = imageData.data.length / 4;
  // 解析之后进行算法运算
  for (var i = 0; i < imageData_length; i++) {
    imageData.data[i * 4 + 1] = 0;
    imageData.data[i * 4 + 2] = 0;
  }
  return imageData
}
//中国版画效果
function chineseColor(imageData) {
  var imageData_length = imageData.data.length / 4;
  // 解析之后进行算法运算
  for (var i = 0; i < imageData_length; i++) {
    var red = imageData.data[i * 4];
    var green = imageData.data[i * 4 + 1];
    var blue = imageData.data[i * 4 + 2];
    var gray = 0.3 * red + 0.59 * green + 0.11 * blue;
    var new_black;
    if (gray > 126) {
      new_black = 255;
    } else {
      new_black = 0;
    }
    imageData.data[i * 4] = new_black;
    imageData.data[i * 4 + 1] = new_black;
    imageData.data[i * 4 + 2] = new_black;
  }
  return imageData;
}
//高斯模糊效果
function gaussBlur(imgData) {
  console.log(imgData);
  var pixes = imgData.data;
  var width = imgData.width;
  var height = imgData.height;
  var gaussMatrix = [],
    gaussSum = 0,
    x, y,
    r, g, b, a,
    i, j, k, len;
  var radius = 30;
  var sigma = 5;
  a = 1 / (Math.sqrt(2 * Math.PI) * sigma);
  b = -1 / (2 * sigma * sigma);
  //生成高斯矩阵
  for (i = 0, x = -radius; x <= radius; x++, i++) {
    g = a * Math.exp(b * x * x);
    gaussMatrix[i] = g;
    gaussSum += g;

  }
  //归一化, 保证高斯矩阵的值在[0,1]之间
  for (i = 0, len = gaussMatrix.length; i < len; i++) {
    gaussMatrix[i] /= gaussSum;
  }
  //x 方向一维高斯运算
  for (y = 0; y < height; y++) {
    for (x = 0; x < width; x++) {
      r = g = b = a = 0;
      gaussSum = 0;
      for (j = -radius; j <= radius; j++) {
        k = x + j;
        if (k >= 0 && k < width) { //确保 k 没超出 x 的范围
          //r,g,b,a 四个一组
          i = (y * width + k) * 4;
          r += pixes[i] * gaussMatrix[j + radius];
          g += pixes[i + 1] * gaussMatrix[j + radius];
          b += pixes[i + 2] * gaussMatrix[j + radius];
          // a += pixes[i + 3] * gaussMatrix[j];
          gaussSum += gaussMatrix[j + radius];
        }
      }
      i = (y * width + x) * 4;
      // 除以 gaussSum 是为了消除处于边缘的像素, 高斯运算不足的问题
      // console.log(gaussSum)
      pixes[i] = r / gaussSum;
      pixes[i + 1] = g / gaussSum;
      pixes[i + 2] = b / gaussSum;
      // pixes[i + 3] = a ;
    }
  }
  //y 方向一维高斯运算
  for (x = 0; x < width; x++) {
    for (y = 0; y < height; y++) {
      r = g = b = a = 0;
      gaussSum = 0;
      for (j = -radius; j <= radius; j++) {
        k = y + j;
        if (k >= 0 && k < height) { //确保 k 没超出 y 的范围
          i = (k * width + x) * 4;
          r += pixes[i] * gaussMatrix[j + radius];
          g += pixes[i + 1] * gaussMatrix[j + radius];
          b += pixes[i + 2] * gaussMatrix[j + radius];
          // a += pixes[i + 3] * gaussMatrix[j];
          gaussSum += gaussMatrix[j + radius];
        }
      }
      i = (y * width + x) * 4;
      pixes[i] = r / gaussSum;
      pixes[i + 1] = g / gaussSum;
      pixes[i + 2] = b / gaussSum;
    }
  }
  console.log(imgData);
  return imgData;
}
//浮雕效果与刻雕效果
function reliefProcess(canvasData) {
  //caontext 画布对象  document.querySelector().getContext("2d");
  // conavas document.querySelector().getContext("2d").getImageData();
  console.log("Canvas Filter - relief process");
  copyImageData(canvasData).then(res => {
    var tempCanvasData = res
    for (var x = 0; x < tempCanvasData.width - 1; x++) {
      for (var y = 0; y < tempCanvasData.height - 1; y++) {

        // Index of the pixel in the array    
        var idx = (x + y * tempCanvasData.width) * 4;
        var bidx = ((x - 1) + y * tempCanvasData.width) * 4;
        var aidx = ((x + 1) + y * tempCanvasData.width) * 4;

        // calculate new RGB value
        var nr = tempCanvasData.data[aidx + 0] - tempCanvasData.data[bidx + 0] + 128;
        var ng = tempCanvasData.data[aidx + 1] - tempCanvasData.data[bidx + 1] + 128;
        var nb = tempCanvasData.data[aidx + 2] - tempCanvasData.data[bidx + 2] + 128;
        nr = (nr < 0) ? 0 : ((nr > 255) ? 255 : nr);
        ng = (ng < 0) ? 0 : ((ng > 255) ? 255 : ng);
        nb = (nb < 0) ? 0 : ((nb > 255) ? 255 : nb);

        // assign new pixel value    
        canvasData.data[idx + 0] = nr; // Red channel    
        canvasData.data[idx + 1] = ng; // Green channel    
        canvasData.data[idx + 2] = nb; // Blue channel    
        canvasData.data[idx + 3] = 255; // Alpha channel    
      }
    }
    return tempCanvasData
  });
}

function copyImageData(imagedata) {
  return Promise((resolve, reject) => {
    var imageData = new ImageData(new Uint8ClampedArray(imagedata.data), imagedata.width, imagedata.height)
    resolve(imageData)
  })
}

//马赛克图片效果
function mosaicProcess(oldImg) {
  var size = 2;
  for (var i = 0; i < oldImg.width; i++) {
    for (var j = 0; j < oldImg.height; j++) {
      //从5*5中获取单个像素信息
      var color = getPxInfo(oldImg, Math.floor(i * size + Math.random() * size),
        Math.floor(j * size + Math.random() * size))
      //写入单个像素信息
      for (var a = 0; a < size; a++) {
        for (var b = 0; b < size; b++) {
          setPxInfo(oldImg, i * size + a, j * size + b, color);
        }
      }
    }
  }
  return oldImg
}
//读取单个像素信息
function getPxInfo(imgDate, x, y) {
  var colorArr = [];
  var width = imgDate.width;
  colorArr[0] = imgDate.data[(width * y + x) * 4 + 0]
  colorArr[1] = imgDate.data[(width * y + x) * 4 + 1]
  colorArr[2] = imgDate.data[(width * y + x) * 4 + 2]
  colorArr[3] = imgDate.data[(width * y + x) * 4 + 3]
  return colorArr;
}
//写入单个像素信息
function setPxInfo(imgDate, x, y, colors) {
  //（x,y） 之前有多少个像素点 == width*y + x
  var width = imgDate.width;
  imgDate.data[(width * y + x) * 4 + 0] = colors[0];
  imgDate.data[(width * y + x) * 4 + 1] = colors[1];
  imgDate.data[(width * y + x) * 4 + 2] = colors[2];
  imgDate.data[(width * y + x) * 4 + 3] = colors[3];
}

//获取不同功能颜色数据
function getFunImageData(btnName, imageDatas) {
  switch (btnName) {
    case buttons[0]:
      return reverseColor(imageDatas)
    case buttons[1]:
      return removeColor(imageDatas)
    case buttons[2]:
      return singleColor(imageDatas)
    case buttons[3]:
      return chineseColor(imageDatas)
    case buttons[4]:
      return gaussBlur(imageDatas)
    case buttons[5]:
      return mosaicProcess(imageDatas)
    case buttons[6]:
      return imageDatas
  }
}

const buttons = ["反色效果", "去色效果", "单色效果", "中国版画效果", "高斯模糊效果", "马赛克", "原图"]

module.exports = {
  getFunImageData,
  getImageColor,
  reverseColor,
  removeColor,
  buttons
}